package resml

import (
	"errors"
	"fmt"
	"strings"
)

var (
	ErrNotImplemented = errors.New("not implemented")
	ErrRemoteReadonly = errors.New("remote resource is read only")
	ErrTimeout        = errors.New("timeout")
	ErrNoMeta         = errors.New("no meta")
	ErrWriting        = errors.New("resource is writing")
)

type MultiError struct {
	errors []error
}

// 创建一个 MultiError
func NewMultiError(errs ...error) *MultiError {
	me := &MultiError{}
	return me.Add(errs...)
}

// 选择错误：如果有多个不为 nil 的 error，则返回 MultiError；
// 如果只有一个不为 nil 的 error，则返回该 error；
// 否则返回 nil （无错误）
func SelectError(errs ...error) error {
	me := NewMultiError(errs...)
	if size := me.Size(); size > 1 {
		return me
	} else if size == 1 {
		return me.errors[0]
	}
	return nil
}

func (m *MultiError) Add(errs ...error) *MultiError {
	if len(errs) <= 0 {
		return m
	}
	if m.errors == nil {
		m.errors = make([]error, 0, len(errs))
	}
	for _, err := range errs {
		if err == nil {
			continue
		}
		if me, ok := err.(*MultiError); ok {
			m.errors = append(m.errors, me.errors...)
			continue
		}
		m.errors = append(m.errors, err)
	}
	return m
}

func (m *MultiError) Size() int {
	return len(m.errors)
}

func (m *MultiError) Errors() []error {
	if m == nil {
		return make([]error, 0)
	}
	return m.errors
}

func (m *MultiError) Error() string {
	if m == nil || len(m.errors) == 0 {
		return "multi errors: no error"
	}
	var sb strings.Builder
	sb.WriteString("multi errors: \n")
	for i, err := range m.errors {
		sb.WriteString(fmt.Sprintf("%d: %v\n", i+1, err))
	}
	return sb.String()
}
